package com.zjcode.cdcer.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.utils.StrUtils;
import com.google.common.collect.Maps;
import com.zjcode.cdcer.config.DataPushConfig;
import com.zjcode.cdcer.enums.DyeCodeEnum;
import com.zjcode.cdcer.mapper.CerSysteminitImportInfoMapper;
import com.zjcode.cdcer.mapper.CerSysteminitImportOfficialInfoMapper;
import com.zjcode.cdcer.mapper.TkmSysOrgMapper;
import com.zjcode.cdcer.mapper.TkmSysUserMapper;
import com.zjcode.cdcer.model.*;
import com.zjcode.cdcer.model.basic.JsonObj;
import com.zjcode.cdcer.model.response.ResponseDataResult;
import com.zjcode.cdcer.model.response.ResponseInfoResult;
import com.zjcode.cdcer.model.response.ResponseResult;
import com.zjcode.cdcer.model.response.ResponseUploadResult;
import com.zjcode.cdcer.service.CerPersonInfoService;
import com.zjcode.cdcer.service.DataPushNationService;
import com.zjcode.cdcer.service.TkmEndoscopeDiagnoseNounInfoService;
import com.zjcode.cdcer.service.ZjcodeSelfTestInfoService;
import com.zjcode.cdcer.utils.RedisUtils;
import com.zjcode.cdcer.utils.RestTemplateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.io.File;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.chinatechstar.component.commons.cache.RedisKey.COUNTRY_CROWD_TOKEN;

/**
 * @Description 推送病理、内镜数据到国家平台
 * @Author bqyang
 * @Date 2024/4/3 14:35
 * @Version 1.0
 */
@Slf4j
@Service
public class DataPushNationServiceImpl implements DataPushNationService, BaseService {

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private CerSysteminitImportInfoMapper cerSysteminitImportInfoMapper;

    @Autowired
    private CerSysteminitImportOfficialInfoMapper cerSysteminitImportOfficialInfoMapper;

    @Autowired
    private TkmEndoscopeDiagnoseNounInfoService tkmEndoscopeDiagnoseNounInfoService;
    @Autowired
    private TkmSysOrgMapper sysOrgMapper;
    @Autowired
    private TkmSysUserMapper sysUserMapper;

    @Autowired
    private ZjcodeSelfTestInfoService zjcodeSelfTestInfoService;
    @Autowired
    private CerPersonInfoService personInfoService;

    @Override
    public JsonObj pushNation(List<String> ids, String userI) {
        if (CollectionUtils.isEmpty(ids)) {
           return JsonObj.error("请选择上报数据！");
        }

        List<PushDataInfo> list = cerSysteminitImportInfoMapper.getPushNationList(ids);
        if (CollectionUtils.isEmpty(list)){
            return JsonObj.error("未查询到未上报数据");
        }
        String token = getLoginToken(userI);
        if ( ObjectUtils.isEmpty(token)){
            return JsonObj.error("连接国家数据平台异常,请联系管理员！");
        }

        for (PushDataInfo v: list) {
            if ( ObjectUtils.isEmpty(v.getWrittenConsentFilePath())) {
                return JsonObj.error(v.getName() + "- 知情同意书未上传！");
            }

            // 根据身份证号码进行查询是否已经存在
            ResponseDataResult responseResult = this.getDataInfo(v, token);
            ResponseResult result = null;
            if (responseResult.getTotal().equals(NumberUtils.INTEGER_ZERO)) {
                 // 1. 上传知情同意书
                ResponseUploadResult uploadResult = this.pushUploadOne( token, v.getWrittenConsentFilePath());
                if ( uploadResult.getCode() != HttpStatus.OK.value()){
                    return JsonObj.error(v.getName() + "-" + uploadResult.getMsg());
                }
                // 2. 更新知情同意书在线地址
                v.setConsent_form_image(uploadResult.getData().getUrl());
                // 3. 数据上报推送创建
                result = this.pushCreate(v, token);
                if ( result.getCode() == HttpStatus.OK.value()){
                    // 数据创建后，上传内镜、病理、自测表数据
                    v.setId(result.getData().getId());
                    v.setConsent_form_image(result.getData().getConsent_form_image());
                    this.dataPushUpdate(v, token, false);
                }
            } else {
                // 3.2 数据更新，更新病理/内镜信息

                PushDataInfo info = responseResult.getData().get(0);
                v.setId(info.getId());
                v.setConsent_form_image(info.getConsent_form_image());
                result = this.dataPushUpdate(v, token, true);
            }

            if ( result.getCode() != HttpStatus.OK.value()) {
                return JsonObj.error(v.getName() + "-" + result.getMsg());
            }

            cerSysteminitImportInfoMapper.updateCrowdStatus(v.getInfoId());
        }

        return JsonObj.success("上报成功");
    }

    @Override
    public JsonObj pushFormalNation(List<String> ids, String userI) {
        if (CollectionUtils.isEmpty(ids)) {
            return JsonObj.error("请选择上报数据！");
        }
        List<PushDataInfo> list = cerSysteminitImportOfficialInfoMapper.getPushNationList(ids);
        if (CollectionUtils.isEmpty(list)){
            return JsonObj.error("未查询到未上报数据");
        }
        String token = getLoginToken(userI);
        if ( ObjectUtils.isEmpty(token)){
            return JsonObj.error("连接国家数据平台异常！,请联系管理员");
        }

        for (PushDataInfo v: list) {
            if ( ObjectUtils.isEmpty(v.getWrittenConsentFilePath())) {
                return JsonObj.error(v.getName() + "- 知情同意书未上传！");
            }

            // 根据身份证号码进行查询是否已经存在
            ResponseDataResult responseResult = this.getDataInfo(v, token);
            ResponseResult result = null;
            if (responseResult.getTotal().equals(NumberUtils.INTEGER_ZERO)) {
                // 1. 上传知情同意书
                ResponseUploadResult uploadResult = this.pushUploadOne( token, v.getWrittenConsentFilePath());
                if ( uploadResult.getCode() != HttpStatus.OK.value()){
                    return JsonObj.error(v.getName() + "-" + uploadResult.getMsg());
                }
                // 2. 更新知情同意书在线地址
                v.setConsent_form_image(uploadResult.getData().getUrl());
                // 3. 数据上报创建
                result = this.pushCreate(v, token);
                if ( result.getCode() == HttpStatus.OK.value()){
                    // 数据更新
                    v.setId(result.getData().getId());
                    // 更新知情同意书ID
                    //v.setEndoscope_id(v.getId());
                    this.dataPushUpdate(v, token, false);
                }
            } else {
                // 3.2 数据更新，更新病理/内镜信息
                v.setId(responseResult.getData().get(0).getId());
                result = this.dataPushUpdate(v, token, true);
            }

            if ( result.getCode() != HttpStatus.OK.value()) {
                return JsonObj.error(v.getName() + "-" + result.getMsg());
            }

        }
        return JsonObj.success("上报成功");
    }

    /**
     *  获取 登录 Token
     * @return
     */
    private String getLoginToken(String userId){
        String redisKey = StrUtils.format(COUNTRY_CROWD_TOKEN, userId);
        String cacheCode = redisUtils.get(redisKey);
        if (ObjectUtils.isEmpty(cacheCode)){
            TkmSysUser userInfo = sysUserMapper.selectByPrimaryKey(Long.valueOf(userId));
            TkmSysOrg orgInfo = sysOrgMapper.selectByPrimaryKey(userInfo.getOrgId());
            if (StringUtils.isBlank(orgInfo.getAccount())) {
                return null;
            }

            cacheCode = DataPushConfig.getLoginToken(orgInfo.getAccount(), orgInfo.getPassword());
            redisUtils.psetex(redisKey, cacheCode, 480);
        }
        return cacheCode;
    }

    /**
     *  数据创建
     * @param info
     * @param token
     * @return
     */
    private ResponseResult pushCreate(PushDataInfo info, String token) {
        Map<String ,String> headMap = Maps.newHashMap();
        headMap.put(DataPushConfig.TOKEN_HEADER, DataPushConfig.TOKEN_PREFIX + token);

        ResponseResult response = RestTemplateUtil.restTemplatePost(DataPushConfig.createApi, JSONObject.toJSONString(info),headMap);
        log.info("数据创建返回结果：{}" , JSONObject.toJSONString(response));
        return response;
    }

    /**
     *  数据更新
     * @param info
     * @param token
     * @return
     */
    private ResponseResult dataPushUpdate(PushDataInfo info, String token, boolean isUpdate){

        // 自测表
        this.pushSelfTest(info.getId(), info.getSfz(), token);

        if ( ObjectUtils.isEmpty(info.getBl_num()) && ObjectUtils.isEmpty(info.getNj_num())) {
            log.info("===没有 内镜/病理数据 不需要更新===");
            return new ResponseResult(HttpStatus.OK.value(), "上报成功");
        }

        // 病理报告
        if ( ObjectUtils.isNotEmpty(info.getBl_num())){
            log.info("========病理报告文件:{}", info.getBlReportFilePath());
            this.pushUploadFile(info.getId(), token, 2, info.getBlReportFilePath());
        }

        // 内镜报告
        if (ObjectUtils.isNotEmpty(info.getNj_num())){
            log.info("========病理报告文件:{}", info.getReportFilePath());
            this.pushUploadFile(info.getId(), token, 1, info.getReportFilePath());

            if (StringUtils.isNotBlank(info.getNjzdStr())) {
                List<TkmEndoscopeDiagnoseNounInfo> diagose = tkmEndoscopeDiagnoseNounInfoService.selectByNounIds(Arrays.asList(info.getNjzdStr().split(",")));
                List<String> codeList = diagose.stream().map(TkmEndoscopeDiagnoseNounInfo::getName).collect(Collectors.toList());

                info.setNjzd(JSONObject.toJSON(codeList));

            }
            if (StringUtils.isNotEmpty(info.getDye())) {
                info.setDye(DyeCodeEnum.getValue(info.getDye()));
            }
        }

        if ( !isUpdate) {
            return null;
        }

        return this.pushUpdate(info, token);
    }

    /**
     *  数据更新
     * @param info
     * @param token
     * @return
     */
    private ResponseResult pushUpdate(PushDataInfo info, String token){
        Map<String ,String> headMap = Maps.newHashMap();
        headMap.put(DataPushConfig.TOKEN_HEADER, DataPushConfig.TOKEN_PREFIX + token);
        ResponseResult response = RestTemplateUtil.restTemplatePost(DataPushConfig.updateApi, JSONObject.toJSONString(info),headMap);
        log.info("数据更新返回结果：{}" , JSONObject.toJSONString(response));
        return response;
    }

    /**
     *  数据上报查询，判断是否已经上报过该数据
     * @param info
     * @param token
     * @return
     */
    private ResponseDataResult getDataInfo(PushDataInfo info, String token){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(DataPushConfig.TOKEN_HEADER, DataPushConfig.TOKEN_PREFIX + token);

        MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();
        params.add("name", info.getName());
        params.add("sfz", info.getSfz());

        ResponseEntity<ResponseInfoResult> response = RestTemplateUtil.restTemplateGet(DataPushConfig.indexApi+ "?name="+ info.getName()+"&sfz="+ info.getSfz(), params, httpHeaders);
        log.info("数据更新返回结果：{}" , JSONObject.toJSONString(response.getBody()));
        return response.getBody().getData();
    }

    /**
     *  知情同意书 上传
     * @param token
     * @param filePath
     */
    private ResponseUploadResult pushUploadOne(String token, String filePath){
        File file = new File(filePath);
        if ( !file.exists()){
            return new ResponseUploadResult(201,"知情同意书上传-文件不存在");
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(DataPushConfig.TOKEN_HEADER, DataPushConfig.TOKEN_PREFIX + token);
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        //2.设置内容长度，必须设置
        httpHeaders.setContentLength(file.length());
        //3.设置文件名称，处理文件名是中文的情况
        httpHeaders.setContentDispositionFormData("fileName", URLEncoder.encode(file.getName()));
        // 设置表单内容
        MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
        //formData.add("id", id);
        formData.add("type", 3);
        FileSystemResource resource = new FileSystemResource( file);
        formData.add("file", resource);
        ResponseUploadResult response = RestTemplateUtil.restTemplateFilePost(DataPushConfig.uploadOneApi, formData, httpHeaders);
        log.info("知情同意书上传返回结果：{}" , JSONObject.toJSONString(response));
        return response;
    }

    /**
     *  内镜/病理 报告单上传
     * @param id
     * @param token
     * @param type 1=内镜，2=病理
     * @param file
     */
    private ResponseUploadResult pushUploadFile(Long id, String token, Integer type, String file){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(DataPushConfig.TOKEN_HEADER, DataPushConfig.TOKEN_PREFIX + token);
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

        MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
        formData.add("id", id);
        formData.add("type", type);
        FileSystemResource resource = new FileSystemResource( new File(file));
        formData.add("file", resource);
        ResponseUploadResult response = RestTemplateUtil.restTemplateFilePost(DataPushConfig.uplodaFileAPi, formData, httpHeaders);
        log.info("内镜/病理 报告单上传返回结果：{}" , JSONObject.toJSONString(response));
        return response;
    }

    /**
     *  自测表数据推送
     * @param id
     * @param token
     * @param idCard
     */
    private void pushSelfTest(Long id, String idCard, String token){

        Map<String ,String> headMap = Maps.newHashMap();
        headMap.put(DataPushConfig.TOKEN_HEADER, DataPushConfig.TOKEN_PREFIX + token);

        ZjcodeSelfTestInfo testInfo = zjcodeSelfTestInfoService.queryByIdCard(idCard);
        if (Objects.isNull(testInfo)){
            log.warn("====自测表数据未匹配到:{}", idCard);
            return;
        }

        CerPersonalInfo personalInfo = personInfoService.getPersonInfoByIdCard(idCard);

        PushSelfTestDataInfo testDataInfo = new PushSelfTestDataInfo();
        testDataInfo.setPersonal_formal_id(id);
        testDataInfo.setSelfTestData(testDataInfo, personalInfo, testInfo);
        log.info("====测表数据推送数据：{}" , JSONObject.toJSONString(testDataInfo));
        ResponseEntity<String> response = RestTemplateUtil.restSelfPost(DataPushConfig.selfTestApi, JSONObject.toJSONString(testDataInfo), headMap);
        log.info("====测表数据推送返回结果：{}" , JSONObject.toJSONString(response));

    }
}
